package org.example.gen;

import cn.hutool.core.io.FileUtil;
import com.grandtech.tools.MapScreenshotTool;
import com.grandtech.tools.ScreenshotWaterSetting;
import com.grandtech.tools.ScreenshotsSetting;
import com.grandtech.tools.Transformation;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Geometry;
import org.example.*;
import org.example.area.AreaList;
import org.example.entity.TotalVillageInfo;
import org.example.tool.ImageUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 坐落图生成工具
 */
public class LocationMapGen implements CallBack {
    private final ShapeEntity shapeEntity;
    private LogInterface log;
    private BigDecimal zzbz;
    private BigDecimal ybzb;
    private boolean isAll;//是否是全量出图
    private static String HB_URL="https://raster.agribigdata.com.cn:443/rest/hebeiimg_241126/wmts?SERVICE=WMTS&REQUEST=GetTile&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpgpng";
    private static String SHENG_URL="https://api.grandtechmap.com/tdt-proxy-server/yxdt/gymap?x={x}&y={y}&l={z}&access_token=tiletoken.mtyynje0mtm4mjyzotzjztgzmmqzzdmzzjrmogjhndvjowqwowjjy2m2njrk";
    private Map<String,List<LandEntity>> tempLands;
    private Map<String,List<Map<String, Object>>> inspectionReportList;
    private boolean isSelected;
    private Map<String, TotalVillageInfo> totalVillageInfoMap;


    public LocationMapGen(ShapeEntity shapeEntity, LogInterface log,BigDecimal zzbz, BigDecimal ybzb,boolean isAll,boolean isSelected) {
        this.shapeEntity = shapeEntity;
        this.log = log;
        this.zzbz = zzbz;
        this.ybzb = ybzb;
        this.isAll=isAll;
        tempLands=new HashMap<>();
        inspectionReportList=new HashMap<>();
        this.isSelected=isSelected;
        totalVillageInfoMap=new HashMap<>();
    }

    @Override
    public boolean doWork(String nf, String bxgsmc, String qhdm, String zwmc, String rootDirPath) {
        List<LandEntity> lands = shapeEntity.getLands().stream().filter(
                landEntity -> landEntity.getNf().equals(nf) &&
                        landEntity.getBxgsmc().equals(bxgsmc) &&
                        landEntity.getQhdm().equals(qhdm) &&
                        landEntity.getZwmc().equals(zwmc)
        ).collect(Collectors.toList());
        if(lands.isEmpty()){
            log.logWarn(String.format("%s-%s-%s-%s未找到匹配的记录", nf,bxgsmc,qhdm,zwmc));
            return true;
        }
        //根据nhdm去重的数量
        long totalPerson=lands.stream().map(LandEntity::getNhdm).distinct().count();
        BigDecimal totalMj=lands.stream().map(LandEntity::getTbmj).reduce(BigDecimal.ZERO, BigDecimal::add);
        totalVillageInfoMap.put(qhdm+zwmc,new TotalVillageInfo(totalPerson,totalMj));
        String fullAreaName= AreaList.getInstance().getAreaData().get(qhdm);
        String dirPath=rootDirPath+File.separator +"坐落图" ;

        //筛选ct为1的记录
        List<LandEntity> landsEqualOne = lands.stream().filter(landEntity -> landEntity.getCt().compareTo(new BigDecimal(1))==0).collect(Collectors.toList());
        if(landsEqualOne.isEmpty()){
            //统计lands nhdm不重复的数量
           Integer farmCount= (int) lands.stream().map(LandEntity::getNhdm).distinct().count();
           if(isAll){
               //全量出图
             //zzzb小于zzbz的记录中的nhdm
               List<String> nhdmsUnneed = lands.stream().filter(landEntity -> landEntity.getZzzb().compareTo(zzbz)<0).map(LandEntity::getNhdm).distinct().collect(Collectors.toList());
               //lands中都大于等于zzbz的记录的农户
               Integer n1=farmCount-nhdmsUnneed.size();
               //如果n1小于farmCount乘以ybzb
               // 使用BigDecimal进行精确比较
               if (new BigDecimal(n1).compareTo(new BigDecimal(farmCount).multiply(ybzb).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP)) < 0) {
                   log.logInfo(String.format("%s-%s-%s-%s有ct不为1的记录,且全量出图占比小于%s，不出图", nf,bxgsmc,qhdm,zwmc,ybzb));
                   //删除文件夹
                   FileUtil.del(dirPath);
               }else {
                   log.logInfo(String.format("%s-%s-%s-%s有ct不为1的记录,且全量出图占比大于%s，出图", nf,bxgsmc,qhdm,zwmc,ybzb));
                   // 抽取农户,n1乘以ybzb,除以100，向上取整
                   BigDecimal n1Decimal = new BigDecimal(farmCount);
                   BigDecimal HUNDRED = new BigDecimal("100");
                   BigDecimal percentage = n1Decimal.multiply(ybzb).divide(HUNDRED, 2, RoundingMode.HALF_UP);
                   int needCount = percentage.setScale(0, RoundingMode.CEILING).intValue();
                   List<String> nhdmsNeed = lands.stream().filter(landEntity -> !nhdmsUnneed.contains(landEntity.getNhdm())).map(LandEntity::getNhdm).distinct().collect(Collectors.toList());
                    //根据zzzb和nhdm对应的记录数量，都是从大到小，排名前needCount的nhdm
                   List<String> topNhdms = nhdmsNeed.stream()
                           .map(nhdm -> {
                               // 计算该nhdm对应的记录数量和zzzb总和
                               List<LandEntity> nhdmLands = lands.stream()
                                       .filter(land -> land.getNhdm().equals(nhdm))
                                       .collect(Collectors.toList());

                               BigDecimal totalZzzb = nhdmLands.stream()
                                       .map(LandEntity::getZzzb)
                                       .max(BigDecimal::compareTo)
                                       .orElse(BigDecimal.ZERO);

                               int recordCount = nhdmLands.size();

                               return new AbstractMap.SimpleEntry<>(nhdm,
                                       new AbstractMap.SimpleEntry<>(totalZzzb, recordCount));
                           })
                           .sorted((entry1, entry2) -> {
                               // 先按zzzb总和从大到小排序
                               int zzzbCompare = entry2.getValue().getKey().compareTo(entry1.getValue().getKey());
                               if (zzzbCompare != 0) {
                                   return zzzbCompare;
                               }
                               // 如果zzzb相同，则按记录数量从小到大排序
                               return Integer.compare( entry1.getValue().getValue(),entry2.getValue().getValue());
                           })
                           .limit(needCount)
                           .map(Map.Entry::getKey)
                           .collect(Collectors.toList());
                   List<LandEntity> landsNeed = lands.stream().filter(landEntity -> topNhdms.contains(landEntity.getNhdm())) .collect(Collectors.toList());
                   //生成坐落图
                   makeLocationMap(landsNeed,dirPath,fullAreaName);
                   tempLands.put(qhdm+zwmc,landsNeed);
               }

           }else {//最高占比出图
               //选取zzzb大于等于zzbz的及记录中的农户数量
               List<String> n1= lands.stream().filter(landEntity -> landEntity.getZzzb().compareTo(zzbz)>=0).map(LandEntity::getNhdm).distinct().collect(Collectors.toList());
               List<String> n2= lands.stream().filter(landEntity -> landEntity.getTbmj().compareTo(landEntity.getQqmj())<=0&&n1.contains(landEntity.getNhdm())).map(LandEntity::getNhdm).distinct().collect(Collectors.toList());
               BigDecimal percentageThreshold = BigDecimal.valueOf(farmCount).multiply(ybzb).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
               if(n2.size() >= percentageThreshold.intValue()){
                   log.logInfo(String.format("%s-%s-%s-%s最高占比出图,且占比大于%s，出图", nf,bxgsmc,qhdm,zwmc,ybzb));
                   //从lands筛选中nhdm在n2的记录，切每个n2记录对应的记录，只保留zzzb最高的一条记录
                   List<LandEntity> landsNeed = lands.stream().filter(landEntity -> n2.contains(landEntity.getNhdm())) .collect(Collectors.toList());
                   //过滤小于确权面积的
                   landsNeed=landsNeed.stream().filter(landEntity -> landEntity.getTbmj().compareTo(landEntity.getQqmj())<=0).collect(Collectors.toList());
                   List<LandEntity> landsNeed1 = landsNeed.stream().collect(Collectors.groupingBy(LandEntity::getNhdm))
                           .values().stream()
                           .map(list -> list.stream().max(Comparator.comparing(LandEntity::getZzzb)).get())
                           .collect(Collectors.toList());
                   //生成坐落图
                   makeLocationMap(landsNeed1,dirPath,fullAreaName);
                   tempLands.put(qhdm+zwmc,landsNeed1);

               }else {
                   log.logInfo(String.format("%s-%s-%s-%s最高占比出图,且占比小于%s，不出图", nf,bxgsmc,qhdm,zwmc,ybzb));
                   FileUtil.del(dirPath);
               }


           }
        }else {
            log.logInfo(String.format("%s-%s-%s-%s有ct为1的记录", nf,bxgsmc,qhdm,zwmc));
            //出图
            makeLocationMap( landsEqualOne,dirPath, fullAreaName);
            tempLands.put(qhdm+zwmc,landsEqualOne);
        }

        //生成坐落图
        //生成总图
        return true;
    }

    private void createDir(String dirPath) {
        if (!isSelected) {
            // 使用Hutool的FileUtil确保父目录存在
            FileUtil.mkParentDirs(dirPath);
            return;
        }
        // 使用Hutool的FileUtil创建目录
        FileUtil.mkdir(dirPath);
    }

    private  void makeLocationMap(List<LandEntity>  lands, String dirPath, String fullAreaName) {

        if(lands.isEmpty()){
            return;
        }

        String color=queryColorFromDic(lands.get(0).getZwdm());
       // 按农户分组处理
       Map<String, List<LandEntity>> landsByNhdm = lands.stream()
               .collect(Collectors.groupingBy(LandEntity::getNhdm));
       createDir(dirPath);
       for (Map.Entry<String, List<LandEntity>> entry : landsByNhdm.entrySet()) {
           List<LandEntity> nhdmLands = entry.getValue();
           // 为每个地块生成图像
           if(isSelected){
               for (int i=1; i <= nhdmLands.size(); i++) {
                   String dkxh = i+""; // 获取地块序号
                   LandEntity landEntity=nhdmLands.get(i-1);
                   ArrayList<String> waterList = new ArrayList<>();
                   waterList.add("投保面积:" + landEntity.getTbmj()+ "(亩)");
                   waterList.add("地块面积:" + landEntity.getQqmj() + "(亩)");
                   waterList.add("农户姓名:" + landEntity.getNhxm());
                   BufferedImage image = LocationMapGen.generate(landEntity.getWkt(), waterList, color, true);
                   String fileName = String.format("%s(%s)地块%S.jpg",landEntity.getNhxm(),landEntity.getNhdm().substring(landEntity.getNhdm().length()-4),dkxh);
                   fileName=dirPath+ File.separator+fileName;
//               //保存图片
                   saveBufferedImage(image, fileName);
               }
           }
           LandEntity farmerLocationMapDTO=nhdmLands.get(0);
           // 生成户级坐落图
           //投保面积求和;
           BigDecimal totalTbmj= nhdmLands.stream().map(LandEntity::getTbmj).reduce(BigDecimal.ZERO, BigDecimal::add);
           List<String> wktList = nhdmLands.stream().map(item->{
               if(item.getWkt().contains(";")){
                   return item.getWkt().split(";")[1];
               }else {
                   return item.getWkt();
               }
           }).collect(Collectors.toList());
           double tbmj = totalTbmj.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();


           if(isSelected&&isAll){
               List<String> waterList = new ArrayList<>();
               waterList.add("地点:" + fullAreaName);
               waterList.add("地块数量:" + nhdmLands.size());
               waterList.add("投保面积:"  + tbmj+ "(亩)");
               waterList.add("农户姓名:" + farmerLocationMapDTO.getNhxm());
               BufferedImage bufferedImage = generate(wktList, waterList,color);
               String fileName = String.format("%s(%s)地块总.jpg",farmerLocationMapDTO.getNhxm(),farmerLocationMapDTO.getNhdm().substring(farmerLocationMapDTO.getNhdm().length()-4));
               //保存图片
               saveBufferedImage(bufferedImage, dirPath+ File.separator+fileName);
           }


           Map<String, Object> map=new HashMap<String, Object>();
           map.put("nhxm", farmerLocationMapDTO.getNhxm());
           map.put("tbdh",AreaList.getAreaName(farmerLocationMapDTO.getQhdm()));
           map.put("tbmj",tbmj);
           map.put("nhdm",farmerLocationMapDTO.getNhdm());
           map.put("sffh", "是");
           map.put("bz", "");
           String key = farmerLocationMapDTO.getQhdm() + farmerLocationMapDTO.getZwmc();
           inspectionReportList.computeIfAbsent(key, k -> new ArrayList<>()).add(map);

       }

   }



    public static BufferedImage generate(String wkt, List<String> waterList, String fillColor, Boolean isHb) {
        try {
            if(wkt.startsWith("SRID=4326;")){
                wkt = wkt.split(";")[1];
            }
            List<String> wktList = Arrays.asList(wkt);
            ScreenshotsSetting screenshotsSetting = prepareScreenshotsSetting(fillColor);
            String color = "#C2180C";
            RGB rgb = ColorConverter.toRGB(color);
            screenshotsSetting.setColor(new Color(rgb.getRed(), rgb.getGreen(), rgb.getBlue()));
            screenshotsSetting.setDrawPolygonMark(true);
            screenshotsSetting.setDrawRect(false);
            screenshotsSetting.setStrokeSize(2.0f);
            List<ScreenshotWaterSetting> waterSettingList = transferWater(waterList);
            screenshotsSetting.setLeftBottomWaters(waterSettingList);
            String imgCustomUrl = HB_URL;
            System.out.println("农户："+imgCustomUrl+"，开始生成坐落图:");
            BufferedImage bufferedImage = MapScreenshotTool.createMapScreenshots(convertToFeatureCollection(wktList),imgCustomUrl,screenshotsSetting);
            if(isHb&& ImageUtils.isSimpleColorImg(bufferedImage,10)){
                System.out.println("河北坐落图生成，存在黑底影像，切换天地图重新生成");
                String imageUrl = SHENG_URL;
                bufferedImage = MapScreenshotTool.createMapScreenshots(convertToFeatureCollection(wktList),imageUrl,screenshotsSetting);
            }
            return bufferedImage;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("生成坐落图失败");
        }
    }
    public static BufferedImage generate(List<String> wktList, List<String> waterList,String fillColor) {
        try {
            String imgCustomUrl = HB_URL;
            ScreenshotsSetting screenshotsSetting = prepareScreenshotsSetting(fillColor);
            List<ScreenshotWaterSetting> waterSettingList = transferWater(waterList);
            screenshotsSetting.setLeftBottomWaters(waterSettingList);
            BufferedImage bufferedImage = MapScreenshotTool.createMapScreenshots(convertToFeatureCollection(wktList),imgCustomUrl,screenshotsSetting);
            return bufferedImage;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("生成坐落图失败");
        }
    }
    private static ScreenshotsSetting prepareScreenshotsSetting(String color){
        ScreenshotsSetting screenshotsSetting = new ScreenshotsSetting();
        Font font = new Font("宋体", Font.BOLD, 14);
        screenshotsSetting.setFont(font);
        screenshotsSetting.setImageScale(1.0f);
        screenshotsSetting.setSocketTimeout(2000);
        if(null!=color){
            RGB rgb = ColorConverter.toRGB(color);
            Color fillColor = new Color(rgb.getRed(), rgb.getGreen(), rgb.getBlue());
            screenshotsSetting.setFillColor(fillColor);
            screenshotsSetting.setFillType(ScreenshotsSetting.FILL);
        }else{
            screenshotsSetting.setFillColor(null);
        }
        return screenshotsSetting;
    }
    private static List<ScreenshotWaterSetting> transferWater(List<String> waterList){
        List<ScreenshotWaterSetting> waterSettingList = new ArrayList<>();
        for(String water:waterList){
            ScreenshotWaterSetting screenshotWaterSetting = new ScreenshotWaterSetting();
            screenshotWaterSetting.setWaterMsg(water);
            screenshotWaterSetting.setFont(new Font("宋体", Font.BOLD, 14));
            waterSettingList.add(screenshotWaterSetting);
        }
        return waterSettingList;
    }
    private static FeatureCollection convertToFeatureCollection(List<String> wkts){
        List<Feature> featureList = new ArrayList<>();
        wkts.forEach(wkt->{
            if(wkt.startsWith("SRID=4326;")){
                wkt = wkt.split(";")[1];
            }
            Geometry geometry = Transformation.wkt2BoxGeometry(wkt);
            Feature feature = Feature.fromGeometry(geometry);
            featureList.add(feature);
        });
        return FeatureCollection.fromFeatures(featureList);
    }

    private static String queryColorFromDic(String zwdm){
        String defaultColor = "#6DB36D";
        try{
            Optional<PlantTypeEnum> res = PlantTypeEnum.getByCode(zwdm);
            // 判断是否匹配到
            if(res.isPresent()){
                return res.get().getColor();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return defaultColor;
    }
    private static void saveBufferedImage(BufferedImage image, String filePath) {
        try {
            // 确保目录存在
            File file = new File(filePath);
            file.getParentFile().mkdirs();

            // 根据文件扩展名确定图像格式
            String format = "png";
            if (filePath.toLowerCase().endsWith(".jpg") || filePath.toLowerCase().endsWith(".jpeg")) {
                format = "jpg";
            } else if (filePath.toLowerCase().endsWith(".bmp")) {
                format = "bmp";
            }

            // 保存图像
            ImageIO.write(image, format, file);
            System.out.println("图像已保存: " + filePath);
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("保存图像失败: " + e.getMessage());
        }
    }


    public Map<String,List<LandEntity>> getTempLands() {
        return tempLands;
    }

    public Map<String,List<Map<String, Object>>> getInspectionReportList() {
        return inspectionReportList;
    }


    public Map<String, TotalVillageInfo> getTotalVillageInfoMap() {
        return totalVillageInfoMap;
    }

    public boolean isAll() {
        return isAll;
    }
}
